package com.wondream.rabbitmq.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer03_routing_email {
    // 队列名称
    private static final String QUEUE_INFORM_EMAIL = "queue_routing_inform_email";
    private static final String EXCHANGE_ROUTING_INFORM = "exchange_routing_inform";
    private static final String ROUTINGKEY_EMAIL = "routingkey_email";

    public static void main(String []args) throws IOException, TimeoutException {// 通过连接工厂创建新的连接和mq建立连接
        // 通过连接工厂创建新的连接和mq建立连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        // 设置虚拟目录
        connectionFactory.setVirtualHost("/");
        // 建立新连接
        Connection connection = connectionFactory.newConnection();
        // 创建会话通道channel
        Channel channel = connection.createChannel();
        // 使用默认交换机
        // 声明队列 如果队列在mq中没有则要创建
        // 参数：String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
        /**
         * 参数说明
         * 1、queue 队列名称
         * 2、durable 是否持久化，如果持久化，mq重启后队列还在
         * 3、exclusive 是否独占连接，队列只允许在该连接中访问，如果连接关闭队列自动删除，如果将此参数设置true可以用于临时队列的创建
         * 4、autoDelete 队列不再使用时自动删除。如果将此参数和exclusive参数设置为true就可以实现临时队列
         * 5、argumens 参数，可以设置一个队列的扩展参数
         */
        channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);

        // 声明一个交换机
        // 参数：String exchange, String type
        /**
         * 参数明细
         * 1、交换机的名称
         * 2、交换机的类型
         */
        channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);

        // 进行交换机和队列绑定
        // 参数：String queue, String exchange, String routingKey
        /**
         * 参数明细
         * 1、queue 队列名称
         * 2、exchange 交换机名称
         * 3、routingKey 路由key，在发布订阅模式中为空字符串
         */
        channel.queueBind(QUEUE_INFORM_EMAIL, EXCHANGE_ROUTING_INFORM, ROUTINGKEY_EMAIL);

        // 实现消费方法
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
            /**
             * 当接收到消息后此方法被调用
             * @param consumerTag 消费者标签，用来标识消费者，在basicConsume可以设置
             * @param envelope 信封，通过envelope可以
             * @param properties 消息属性 对应发送的消息属性
             * @param body 消息内容
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                // 交换机
                String exchange = envelope.getExchange();
                // 消息id，mq在channel中用来标识消息的id，可用于消息的确认
                long deliveryId = envelope.getDeliveryTag();
                // 消息内容
                String messages = new String(body, "utf-8");
                System.out.println("receive message:"+messages);
            }
        };

        // 监听队列
        // 参数：String queue, boolean autoAck, Consumer callback
        /**
         * 参数明细
         * 1、queue 队列名称
         * 2、autoAck 自动回复，当消费者接收到消息后要告诉mq消息已接收，如果将此参数设置为true表示会自动回复mq，如果设置为false要通过编程实现回复
         * 3、callback 消费方法，当消费者接收到消息要执行的方法
         */
        channel.basicConsume(QUEUE_INFORM_EMAIL, true, defaultConsumer);


    }
}